package com.fang.sort;

import java.util.Comparator;

import com.fang.base.utils.SwapUtils;

/**
 * 冒泡排序
 * 
 * @author fang min
 *
 */
public class BubbleSort {

	public static void main(String[] args) {
		Integer[] sort = { 2, 5, 45, 87, 1, 254, 58 };
		Integer[] sort2 = { 2, 5, 45, 87, 1, 254, 58 };
		Integer[] sort3 = { 2, 5, 45, 87, 1, 254, 58 };

		Integer[] sortDes = BubbleSort.sort(sort, new Comparator<Integer>() {

			@Override
			public int compare(Integer data1, Integer data2) {
				if (data1 < data2)
					return 1;
				if (data1 > data2)
					return -1;
				return 0;
			}
		});

		Integer[] sortDes2 = BubbleSort.sort2(sort2, new Comparator<Integer>() {

			@Override
			public int compare(Integer data1, Integer data2) {
				if (data1 < data2)
					return 1;
				if (data1 > data2)
					return -1;
				return 0;
			}
		});

		Integer[] sortDes3 = BubbleSort.sort2(sort3, new Comparator<Integer>() {

			@Override
			public int compare(Integer data1, Integer data2) {
				if (data1 < data2)
					return 1;
				if (data1 > data2)
					return -1;
				return 0;
			}
		});

		for (Integer integer : sortDes) {
			System.out.print(integer + "   ");
		}
		System.out.println("");
		for (Integer integer : sortDes2) {
			System.out.print(integer + "   ");
		}
		System.out.println("");
		for (Integer integer : sortDes3) {
			System.out.print(integer + "   ");
		}
	}

	/**
	 * 冒泡排序算法的运作如下：（从后往前）
	 * 
	 * 比较相邻的元素。如果第一个比第二个大，就交换他们两个。
	 * 对每一对相邻元素作同样的工作，从开始第一对到结尾的最后一对。在这一点，最后的元素应该会是最大- 的数。
	 * 针对所有的元素重复以上的步骤，除了最后一个。 持续每次对越来越少的元素重复上面的步骤，直到没有任何一对数字需要比较。
	 * 
	 * @return
	 */
	public static <T> T[] sort(T[] data, Comparator<? super T> comparator) {
		if (data == null || comparator == null)
			return data;
		int length = data.length;
		for (int i = 0; i < length; i++) {
			for (int j = 0; j < length - 1; j++) {
				if (comparator.compare(data[j], data[j + 1]) < 0) {
					SwapUtils.swap(data, j, j + 1);
				}
			}
		}
		return data;
	}

	/**
	 * 现在我们考虑一种情况，如果某一趟排序过程中，我们没有执行数据交换的过程，这说明我们的数据已经是有序的，
	 * 不需要进行后续的排序过程。为此我们加入了一个“哨兵”变量flag，如果某一趟有数据交换，
	 * 就将哨兵置为true,否则为false。变量flag为false表明整个数组都排序完成。
	 */
	public static <T> T[] sort2(T[] data, Comparator<? super T> comparator) {
		if (data == null || comparator == null)
			return data;
		boolean flag = true;
		while (flag) {
			flag = false;
			int k = data.length - 1;
			for (int j = 0; j < k; j++) {
				if (comparator.compare(data[j], data[j + 1]) < 0) {
					flag = true;
					SwapUtils.swap(data, j, j + 1);
				}
			}
			k--;
		}
		return data;
	}

	/**
	 * 下面我们在考虑一种情况，如果有1000个数的数组，仅前面10个无序，后面990个都已排好序且都大于前面10个数字，那么在第一趟遍历后，
	 * 最后发生交换的位置必定小于10， 且这个位置之后的数据必定已经有序了，记录下这位置，第二次只要从数组头部遍历到这个位置就可以了。
	 * 
	 * @return
	 */
	public static <T> T[] sort3(T[] data, Comparator<? super T> comparator) {
		if (data == null || comparator == null)
			return data;
		int lastSwitchIndex = data.length - 1;

		while (lastSwitchIndex > 0) {
			int k = lastSwitchIndex;
			lastSwitchIndex = 0;
			for (int j = 0; j < k; j++) {
				if (comparator.compare(data[j], data[j + 1]) < 0) {
					lastSwitchIndex = j;
					SwapUtils.swap(data, j, j + 1);
				}
			}
		}
		return data;
	}
}
